home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 15
/
Aminet 15 - Nov 1996.iso
/
Aminet
/
comm
/
bbs
/
s342q16.lha
/
netcache.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-29
|
17KB
|
711 lines
/*
* netcache.c
*
* Networking functions for handling network cache (fast transfers).
*/
/*
* history
*
* 91Sep20 HAW Created.
*/
#include "ctdl.h"
#define MAP_FILE "map.$$$"
#define FAST_TEMPLATE "fast$$$.%s"
#define FAST_RECEIVE "fast_tr.%s"
#define NETMSGS "netmsgs.%s"
/*
* contents
*
*/
char RecMassTransfer;
char MassTransferSent;
char Zmodem = 0;
static int MTCompVal;
extern char logNetResults;
extern char netDebug;
extern CONFIG cfg; /* Lots an lots of variables */
extern char *SR_Sent;
extern MessageBuffer msgBuf;
extern char inReceive;
extern NetBuffer netTemp;
extern char inNet;
extern NetBuffer netBuf;
extern FILE *netLog;
extern rTable *roomTab;
extern FILE *upfd;
extern int callSlot;
extern NetTable *netTab;
extern int thisNet;
extern char *READ_ANY, *APPEND_ANY;
/*
* FileMap
*
* This structure is used to map between a filename and the room it's
* carrying.
*/
typedef struct
{
char *FileName;
char *RoomName;
}
FileMap;
/*
* Mappings
*
* This is a list of mappings for our current work.
*/
static void FreeMapping();
SListBase Mappings =
{
NULL, NULL, NULL, FreeMapping, NULL
};
/*
* SendFastTransfer()
*
* We want to use Facility 21, the mass transfer of messages.
*/
char SendFastTransfer()
{
long size;
extern long netBytes;
extern AN_UNSIGNED RecBuf[SECTSIZE + 5];
struct cmd_data cmds;
char BaseArcName[15], Outgoing;
int protocol;
char ArcFileName[100];
char CacheDir[70];
int RoomOutgoing(SharedRoom *room, int system, int index, int roomslot, char *d);
int UnCacheRoom(SharedRoom *room, int system, int index, int roomslot, void *d);
if ( netDebug )splitF(netLog, "SendFastTransfer:%sabled\n", netBuf.nbflags.MassTransfer ? " En" : "Dis");
if (!netBuf.nbflags.MassTransfer) return FALSE;
if (!netBuf.nbflags.local &&
!(netBuf.nbflags.spine || inReceive))
{
if( netDebug )
{
if( !netBuf.nbflags.local )splitF(netLog, "SendFastTransfer:FALSE, Not Local\n");
if( netBuf.nbflags.spine )splitF(netLog, "SendFastTransfer:FALSE, A Spine\n");
if( inReceive )splitF(netLog, "SendFastTransfer:FALSE, We have been called\n");
}
splitF(netLog, "Mass Transfer flag ignored\n");
return FALSE;
}
if (!CompAvailable(GetCompression(thisNet)))
{
if (netDebug)splitF(netLog, "SendFastTransfer:FALSE, No compression set\n");
return FALSE;
}
/* do we have rooms to send??? */
Outgoing = FALSE;
EachSharedRoom(thisNet, RoomOutgoing, VirtualRoomOutgoing, &Outgoing);
if (!Outgoing)
{
MassTransferSent = TRUE;
EachSharedRoom(thisNet, UnCacheRoom, UnCacheVirtualRoom, NULL);
if (netDebug)splitF(netLog, "SendFastTransfer:FALSE, No rooms to send\n");
return FALSE;
}
zero_struct(cmds);
sPrintf(cmds.fields[0], "%d", GetCompression(thisNet));
sPrintf(cmds.fields[1], "%d", ZM_PROTOCOL);
strCpy(cmds.fields[2], "0");
strCpy(cmds.fields[3], "-1");
cmds.command = FAST_MSGS;
protocol = ZM_PROTOCOL;
if (!Zmodem || FindProtocolCode(Zmodem, FALSE) == -1 ||
!sendNetCommand(&cmds, "mt"))
{
sPrintf(cmds.fields[1], "%d", DEFAULT_PROTOCOL);
protocol = DEFAULT_PROTOCOL;
if (!sendNetCommand(&cmds, "mt"))
{
if( logNetResults && netDebug )splitF(netLog, "Fast Transfer refused\n");
return FALSE;
}
}
if (SendMapFile())
{
if (!MapFileAccepted())
{
if (netDebug)splitF(netLog, "SendFastTransfer:FALSE, MAP File problem\n");
return FALSE;
}
CacheSystem(thisNet, FALSE);
outMod(ACK);
sPrintf(BaseArcName, NETMSGS, CompExtension(GetCompression(thisNet)));
NetCacheName(ArcFileName, thisNet, BaseArcName);
if( logNetResults && netDebug )splitF(netLog, "Mass Transfer: %s\n",ArcFileName);
if (protocol == DEFAULT_PROTOCOL)
SendHostFile(ArcFileName);
else
{
ExternalTransfer(FindProtocolCode(Zmodem, FALSE), ArcFileName);
while (MIReady()) inp();
pause(80); /* keep the other system from eating our NAK */
}
if (gotCarrier())
{
ITL_Receive(NULL, FALSE, TRUE, putFLChar, fclose);
if (RecBuf[0] == BAD || !gotCarrier())
{
if (netDebug)splitF(netLog, "SendFastTransfer:FALSE, lost carrier, or bad transmission\n");
return FALSE;
};
MassTransferSent = TRUE;
EachSharedRoom(thisNet, UnCacheRoom, UnCacheVirtualRoom, NULL);
MakeNetCacheName(CacheDir, thisNet);
if (netDebug)splitF(netLog, "CacheDir:%s\n",CacheDir);
if (ChangeToCacheDir(CacheDir) == 0)
{
netBytes = 0l;
wildCard(getSize, BaseArcName, FALSE, "", FALSE);
size = netBytes;
netBytes = 0l;
wildCard(getSize, CACHED_FILES, FALSE, "", FALSE);
wildCard(DelFile, ALL_FILES, FALSE, "", FALSE);
if( logNetResults && netDebug )splitF(netLog, "MT: %ld => %ld\n", netBytes, size);
}
homeSpace();
return TRUE;
}
}
if (netDebug)splitF(netLog, "SendFastTransfer:FALSE, problem with sendmapfile()\n");
return FALSE;
}
/*
* RoomOutgoing()
*
* This is responsible for deciding if the given shared room has outgoing
* material in a room eligible for mass transfers.
*/
int RoomOutgoing(SharedRoom *room, int system, int index, int roomslot,
char *d)
{
if (strLen(roomTab[roomslot].rtname) && HasOutgoing(system, index))
{
*d = TRUE;
return ERROR;
}
return TRUE;
}
/*
* SendMapFile()
*
* This sends a file containing the names of rooms to share and the filenames
* in the upcoming archive file to map the rooms to. Format is a series of
* pairs of lines (UNIX style), first the roomname and then the filename.
* blank line signals end of file.
*/
char SendMapFile()
{
int NormalRoomMap(SharedRoom *room, int system, int index, int roomslot,
void *d);
if (!ITL_Send(STARTUP)) return FALSE;
EachSharedRoom(thisNet, NormalRoomMap, VirtualRoomMap, NULL);
ITL_Line("");
return ITL_Send(FINISH);
}
/*
* NormalRoomMap()
*
* This sends the given room's name and cache file name if there is an
* outgoing file pending or one will be built.
*/
int NormalRoomMap(SharedRoom *room, int system, int index, int roomslot,
void *d)
{
char work[20];
if (strLen(roomTab[roomslot].rtname) && HasOutgoing(system, index))
{
ITL_Line(roomTab[roomslot].rtname);
sPrintf(work, CACHE_END_NAME, roomslot);
ITL_Line(work);
}
return TRUE;
}
/*
* ITL_Line()
*
* Sends the specified line to the SendITLchar function.
*/
void ITL_Line(char *data)
{
while (*data)
{
sendITLchar((int) *data);
data++;
}
sendITLchar((int) '\n');
}
/*
* DelFile()
*
* This function kills the named file.
*/
void DelFile(DirEntry *f)
{
unlink(f->unambig);
}
/*
* MapFileAccepted()
*
* This function is responsible for discovering if the map file is acceptable.
*/
char MapFileAccepted()
{
FILE *fd;
char toReturn = TRUE, work[NAMESIZE + 5];
ToTempArea();
if (ITL_Receive("moo", FALSE, TRUE, putFLChar, fclose) == ITL_SUCCESS)
{
if ((fd = safeopen("moo", READ_ANY)) == NULL)
toReturn = FALSE;
else
{
GetAString(work, sizeof work, fd);
if (strLen(work) != 0) toReturn = FALSE;
fclose(fd);
unlink("moo");
}
}
else toReturn = FALSE;
KillTempArea();
return toReturn;
}
#define TOP_COMP 4
/*
* netFastTran()
*
* Accept an archive of files?
*/
void netFastTran(struct cmd_data *cmds)
{
char CheckMap(char *fn, char talk);
int MTProtocol;
SYS_FILE fn;
char work[15];
MTCompVal = atoi(cmds->fields[0]);
MTProtocol = atoi(cmds->fields[1]);
if (RecMassTransfer || MTCompVal > TOP_COMP || MTCompVal < 0 ||
!DeCompAvailable(MTCompVal))
{
reply(BAD, "nope");
return;
}
if (MTProtocol == ZM_PROTOCOL)
{
if (!Zmodem || FindProtocolCode(Zmodem, TRUE) == -1)
{
reply(BAD, "No protocol");
return;
}
}
else if (MTProtocol != DEFAULT_PROTOCOL)
{
reply(BAD, "No protocol");
return;
}
if (strCmp(cmds->fields[2], "0") != SAMESTRING ||
strCmp(cmds->fields[3], "-1") != SAMESTRING)
{
reply(BAD, " Field 2 & Field 3 no match");
return;
}
reply(GOOD, "");
makeSysName(fn, MAP_FILE, &cfg.netArea);
if (netDebug)splitF(netLog, "MAP File:%s\n",fn);
if (ITL_Receive(fn, FALSE, TRUE, putFLChar, fclose) != ITL_SUCCESS)
{
return ;
}
KillList(&Mappings);
if (CheckMap(fn, TRUE))
{
splitF(netLog, "Accepting mass transfer %d\n", MTProtocol);
if (receive(120) == NAK) return;
sPrintf(work, FAST_RECEIVE, CompExtension(MTCompVal)); /*** bug fix ***/
/* makeSysName(fn, work, &cfg.netArea); */
ChangeToCacheDir(&cfg.netArea); /*** bug fix ***/
if (netDebug)splitF(netLog, "AMT File(netarea):%s\n",work);
if (MTProtocol == DEFAULT_PROTOCOL)
{
if (netDebug)splitF(netLog, "Protocol: DEFAULT\n",work);
if (ITL_Receive(work,FALSE,TRUE, putFLChar, fclose) != ITL_SUCCESS)
{
return ;
}
}
else if (MTProtocol == ZM_PROTOCOL)
{
if (netDebug)splitF(netLog, "Protocol: Zmodem/External\n",work);
ExternalTransfer(FindProtocolCode(Zmodem, TRUE), work);
while (MIReady()) inp();
}
if (access(fn, 0) == 0 )
{
reply(GOOD, "");
/* recovery setup in case of power failure, etc */
sPrintf(fn, "%s:%d", FAST_RECEIVE, MTCompVal);
UpdateRecoveryFile(fn);
RecMassTransfer = TRUE;
}
else
{
reply(BAD, "No file");
if( logNetResults )splitF(netLog, "File not received:%s\n",fn);
makeSysName(fn, MAP_FILE, &cfg.netArea);
unlink(fn);
}
}
homeSpace();
}
/*
* CheckMap()
*
* Checks the map of room names to see if we refuse any.
*/
char CheckMap(char *fn, char talk)
{
FILE *fd;
char work[2 * NAMESIZE];
char toReturn = TRUE, bad;
FileMap *data;
RoomSearch arg;
if (talk && !ITL_Send(STARTUP)) return FALSE;
if ((fd = safeopen(fn, READ_ANY)) != NULL)
{
while (GetAString(work, sizeof work, fd) != NULL)
{
bad = TRUE;
if (strLen(work) == 0) break;
if (strLen(work) < NAMESIZE)
{
strCpy(arg.Room, work);
if (RoomRoutable(&arg))
{
bad = FALSE;
data = GetDynamic(sizeof *data);
data->RoomName = strdup(work);
GetAString(work, sizeof work, fd);
data->FileName = strdup(work);
if (netDebug)splitF(netLog, "MAP Data:RoomName:%s FileName:%s\n"
,data->RoomName, data->FileName);
AddData(&Mappings, data, NULL, FALSE);
}
}
/* this form lets us respond to several errors with one chunk of code */
if (bad)
{
toReturn = FALSE;
if (talk) ITL_Line(work);
GetAString(work, sizeof work, fd);
}
}
fclose(fd);
}
else
{
printf("Couldn't open %s!\n", fn);
if (talk) ITL_Line("moo");
toReturn = FALSE;
}
if (talk)
{
ITL_Line("");
ITL_Send(FINISH);
}
return toReturn;
}
/*
* FreeMapping()
*
* Frees a mapping structure.
*/
static void FreeMapping(FileMap *data)
{
free(data->FileName);
free(data->RoomName);
free(data);
}
/*
* KillCacheFiles()
*
* This function kills all cache information concerning a node. It is called
* when a node is deleted from the nodelist, NOT when caching is simply turned
* off.
*/
void KillCacheFiles(int which)
{
char ArcFileName[100];
MakeNetCacheName(ArcFileName, which);
/* we check this due to the statement after - kill all files! */
if (ChangeToCacheDir(ArcFileName) == 0)
wildCard(DelFile, ALL_FILES, FALSE, "", FALSE);
homeSpace();
rmdir(ArcFileName);
}
/*
* ReadFastFiles()
*
* This function reads in all of the messages from an Arc file.
*/
void ReadFastFiles()
{
SYS_FILE fn;
char work[15];
void EatMsgFile();
if (!RecMassTransfer) return;
RecMassTransfer = FALSE;
sprintf(work, FAST_RECEIVE, CompExtension(MTCompVal));
makeSysName(fn, work, &cfg.netArea);
if (netDebug)splitF(netLog, "RFF:%s(netarea)\n",fn);
NetDeCompress(MTCompVal, fn);
RunList(&Mappings, EatMsgFile);
KillNetDeCompress();
if (!cfg.BoolFlags.debug) unlink(fn);
makeSysName(fn, MAP_FILE, &cfg.netArea);
if (!cfg.BoolFlags.debug) unlink(fn);
KillList(&Mappings);
homeSpace();
}
/*
* EatMsgFile()
*
* This eats a message file extracted from an archive file.
*/
void EatMsgFile(FileMap *data)
{
char fn[80];
char vfn[70];
int VirtNo;
RoomSearch arg;
extern char *SharingRefusal[];
strCpy(arg.Room, data->RoomName);
if (!RoomRoutable(&arg))
{
if( logNetResults )splitF(netLog, "Ooops - can't find %s\n", data->RoomName);
return;
}
if (arg.virtual)
{
SetUpForVirtuals(arg.index, &VirtNo, vfn);
MakeDeCompressedFilename(fn, data->FileName);
VirtualCopyFileToFile(fn, vfn);
}
else
{
MakeDeCompressedFilename(fn, data->FileName);
ReadNetRoomFile(arg.index, fn);
}
}
/*
* CacheMessages()
*
* This function is tasked with building cache files as needed. We loop
* through all the systems in the system list. Those for which the
* MassTransfer flag is active will cause the system to see if there are
* any messages in the message base that are not in the cache for that
* system. If any are found, the messages are added to their respective
* files (or create as necessary) and then the compression program is run for
* that particular cache. Flags must be set appropriately, of course.
*/
char CacheUpdated;
void CacheMessages(MULTI_NET_DATA whichNets, char VirtOnly)
{
int rover;
for (rover = 0; rover < cfg.netSize; rover++)
{
if ((netTab[rover].ntMemberNets & whichNets))
CacheSystem(rover, VirtOnly);
}
}
/*
* CacheSystem()
*
* This function caches a single system. It is separated from CacheMessages()
* so we can cache systems on an individual basis.
*/
void CacheSystem(int system, char VirtOnly)
{
int CacheRoom(SharedRoom *room, int system, int index, int roomslot, void *d);
extern void (*NetPrintTarget)(char *format, ...);
char ArcFileName[60], Files[60], BaseName[40];
if (!netTab[system].ntflags.MassTransfer) return;
if (!gotCarrier()) DisableModem(TRUE);
CacheUpdated = FALSE;
NetPrintTarget = ToFile;
EachSharedRoom(system, (VirtOnly) ? NULL : CacheRoom,
CacheVirtualRoom, NULL);
if (CacheUpdated)
{
putNet(system, &netBuf);
if (CompAvailable(GetCompression(system)))
{
sPrintf(BaseName, NETMSGS, CompExtension(GetCompression(thisNet)));
NetCacheName(ArcFileName, system, BaseName);
if (netDebug)splitF(netLog, "ArcFileName:%s\n",ArcFileName);
NetCacheName(Files, system, CACHED_FILES);
if (netDebug)splitF(netLog, "Files:%s\n",Files);
Compress(GetCompression(system), Files, ArcFileName);
if (access(ArcFileName, 0) != 0)
{
sPrintf(msgBuf.mbtext, "Compress failed for %s?",
netBuf.netName);
if( logNetResults )splitF(netLog, "ERROR: %s\n", msgBuf.mbtext);
aideMessage("Net Aide", FALSE);
}
}
UpdVirtStuff();
}
if (!gotCarrier()) EnableModem(TRUE);
NetPrintTarget = mTrPrintf;
}
/*
* CacheRoom()
*
* This caches a room's messages as necessary.
*/
int CacheRoom(SharedRoom *room, int system, int index, int roomslot,
void *d)
{
extern char PrTransmit;
char oldNet;
int MsgCount;
extern NetInfo NetStyle;
char work[10], tempNm[3*NAMESIZE], commnd, doit, *name;
if (roomTab[roomslot].rtlastMessage > room->lastMess &&
strLen(roomTab[roomslot].rtname))
{
if (thisNet != system)
getNet(system, &netBuf);
Addressing(system, index, &commnd, &NetStyle.addr1, &NetStyle.addr2,
&NetStyle.addr3, &name, &doit);
NetStyle.sendfunc = putFLChar;
PrTransmit = FALSE;
sPrintf(work, CACHE_END_NAME, roomslot);
NetCacheName(tempNm, system, work);
if ((upfd = safeopen(tempNm, APPEND_ANY)) != NULL)
{
oldNet = inNet;
inNet = NET_CACHE;
MsgCount = showMessages(NEWoNLY, FALSE,
room->lastMess, NetRoute);
inNet = oldNet;
fclose(upfd);
SetHighValues(index);
if (MsgCount == 0 && !GetFA(room->mode))
unlink(tempNm);
else if (MsgCount != 0)
{
SetFA(netBuf.netRooms[index].mode);
CacheUpdated = TRUE;
}
}
PrTransmit = TRUE;
}
return TRUE;
}
/*
* RecoverMassTransfer()
*
* This function is charged with recovering a mass transfer file that was
* not processed in the last net session due to a crash of some sort.
*/
void RecoverMassTransfer(char *line)
{
SYS_FILE fn;
char *colon;
makeSysName(fn, MAP_FILE, &cfg.netArea);
RecMassTransfer = TRUE;
if (netDebug)splitF(netLog, "Recover from:%s\n",fn);
CheckMap(fn, FALSE);
if ((colon = strchr(line, ':')) == NULL) return;
MTCompVal = atoi(colon + 1);
ReadFastFiles();
}
/*
* UnCacheRoom()
*
* This turns off the cached flag for a given room shared thing.
*/
int UnCacheRoom(SharedRoom *room, int system, int index, int roomslot,
void *d)
{
if (strLen(roomTab[roomslot].rtname))
{
UnSetFA(netBuf.netRooms[index].mode);
/* this is valid only so long as we uncache on-line, so in case ... */
if (inNet != NON_NET) SR_Sent[index] = 1;
}
return TRUE;
}